﻿using KELT.KELTObjects.ViewportObjectModel;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.Windows.Shapes;

namespace KELT.Viewport
{
    public class SelectPoint
    {
        public Point centerPoint;
        private Transform3DGroup pointTransform3DGroup;
        private Viewport2DVisual3D pointViusal;
        public Boolean isScale;

        //크기조정을 위한
        public Point3DCollection myPoint3DCollection;

        public SelectPoint(Shape shape)
        {
            centerPoint = new Point();
            pointViusal = new Viewport2DVisual3D();
            pointTransform3DGroup = new Transform3DGroup();


            Canvas Canvas = new Canvas();
            setCanvas(Canvas, shape);
            pointViusal = CreateFront(Canvas, pointTransform3DGroup, 0, 0, 0);

        }

        public void setCanvas(Canvas canvas, Shape rect)
        {
            canvas.Children.Add(rect);
        }

        public Viewport2DVisual3D getPointVisual()
        {
            return pointViusal;
        }


        public Viewport2DVisual3D CreateFront(Canvas p, Transform3DGroup group, double x, double y, double z)
        {
            TranslateTransform3D myTranslateTransform3D = new TranslateTransform3D(x, y, z);

            ScaleTransform3D myScaleTransform3D = new ScaleTransform3D(1, 1, 1);
            myScaleTransform3D.CenterX = x; myScaleTransform3D.CenterY = y; myScaleTransform3D.CenterZ = z;

            RotateTransform3D rotateTransform = new RotateTransform3D();
            rotateTransform.CenterX = x; rotateTransform.CenterY = y; rotateTransform.CenterZ = z;
            rotateTransform.Rotation = new AxisAngleRotation3D { Angle = 0, Axis = new Vector3D(0, 1, 0) };



            group.Children.Add(myTranslateTransform3D);
            group.Children.Add(myScaleTransform3D);
            group.Children.Add(rotateTransform);


            myPoint3DCollection = new Point3DCollection();
            myPoint3DCollection.Add(new Point3D((double)-0.2, 0.2, 0));
            myPoint3DCollection.Add(new Point3D((double)-0.2, -0.2, 0));
            myPoint3DCollection.Add(new Point3D((double)0.2, -0.2, 0));
            myPoint3DCollection.Add(new Point3D((double)0.2, 0.2, 0));

            PointCollection myPointCollection = new PointCollection();
            myPointCollection.Add(new Point(0, 0));
            myPointCollection.Add(new Point(0, 1));
            myPointCollection.Add(new Point(1, 1));
            myPointCollection.Add(new Point(1, 0));

            MeshGeometry3D triangleMesh = new MeshGeometry3D();
            triangleMesh.Positions = myPoint3DCollection;
            triangleMesh.TextureCoordinates = myPointCollection;

            triangleMesh.TriangleIndices.Add(0);
            triangleMesh.TriangleIndices.Add(1);
            triangleMesh.TriangleIndices.Add(2);
            triangleMesh.TriangleIndices.Add(0);
            triangleMesh.TriangleIndices.Add(2);
            triangleMesh.TriangleIndices.Add(3);

            DiffuseMaterial myDiffuseMaterial = new DiffuseMaterial(Brushes.Transparent);
            Viewport2DVisual3D.SetIsVisualHostMaterial(myDiffuseMaterial, true);

            Viewport2DVisual3D v2v3 = new Viewport2DVisual3D();
            v2v3.Transform = group;
            v2v3.Material = myDiffuseMaterial;
            v2v3.Geometry = triangleMesh;
            v2v3.Visual = p;


            return v2v3;
        }

        public Transform3DGroup getPoint3DCollection()
        {
            return pointTransform3DGroup;
        }


    }
    public class SelectBox
    {
        private TOOL mainContext;

        public Object SelectObject;

        private Point3D point;

        //회전조정을 위한
        public Point CenterPoint;

        public Boolean isRotate = false;
        public Boolean isVisible = false;

        public SelectPoint[] pointList = new SelectPoint[9];



        public SelectBox(TOOL mainContext, double x, double y, ViewportObj obj)
        {
            this.mainContext = mainContext;

            double changeX = (x * 2 / mainContext.mainViewport.RenderSize.Width - 1) * (0.4 * mainContext.cameraManager.getPoint3D().Z) + mainContext.cameraManager.getPoint3D().X + mainContext.cameraManager.getTranslateTransform().OffsetX;
            double changeY = (y * -2 / mainContext.mainViewport.RenderSize.Height + 1) * (0.16 * mainContext.cameraManager.getPoint3D().Z) + mainContext.cameraManager.getPoint3D().Y + mainContext.cameraManager.getTranslateTransform().OffsetY;

            point = new Point3D(changeX, changeY, 0);


            CenterPoint = new Point(changeX, changeY);



            Ellipse centerPoint = new Ellipse();
            centerPoint.Fill = new SolidColorBrush(Brushes.White.Color);
            centerPoint.Stroke = Brushes.Black;
            centerPoint.Width = 2;
            centerPoint.Height = 2;
            centerPoint.StrokeThickness = 0.1;

            Rectangle[] rect = new Rectangle[8];
            for (int i = 1; i < pointList.Count(); i++)
            {
                rect[i - 1] = new Rectangle();
                rect[i - 1].Width = 0.5;
                rect[i - 1].Height = 0.7;
                if (i > 4)
                {
                    rect[i - 1].Width = 0.3;
                    rect[i - 1].Height = 0.3;
                    rect[i - 1].Fill = new SolidColorBrush(Brushes.White.Color);
                    rect[i - 1].Stroke = Brushes.Black;
                    rect[i - 1].StrokeThickness = 0.01;
                }
                else
                {
                    rect[i - 1].Fill = new SolidColorBrush(Brushes.White.Color);
                    rect[i - 1].Stroke = Brushes.Black;
                    rect[i - 1].StrokeThickness = 0.01;
                }
            }


            pointList[0] = new SelectPoint(centerPoint);

            for (int i = 1; i < pointList.Count(); i++)
            {
                pointList[i] = new SelectPoint(rect[i-1]);
            }




            centerPoint.MouseDown += new MouseButtonEventHandler(CenterClick);

            rect[0].MouseDown += new MouseButtonEventHandler(ScaleBoxClick1);
            rect[1].MouseDown += new MouseButtonEventHandler(ScaleBoxClick2);
            rect[2].MouseDown += new MouseButtonEventHandler(ScaleBoxClick3);
            rect[3].MouseDown += new MouseButtonEventHandler(ScaleBoxClick4);

            rect[4].MouseDown += new MouseButtonEventHandler(ScaleBoxClick5);
            rect[5].MouseDown += new MouseButtonEventHandler(ScaleBoxClick6);
            rect[6].MouseDown += new MouseButtonEventHandler(ScaleBoxClick7);
            rect[7].MouseDown += new MouseButtonEventHandler(ScaleBoxClick8);


            centerPoint.MouseDown += new MouseButtonEventHandler(obj.setScalePoint);
            for (int i = 0; i < rect.Count(); i++)
            {
                rect[i].MouseDown += new MouseButtonEventHandler(obj.setScalePoint);
            }


        }



        public void visibleSelectBox()
        {

            if (isVisible == false)
            {
                isVisible = true;
                for(int i=0; i<pointList.Count(); i++)
                {
                    mainContext.mainViewport.Children.Add(pointList[i].getPointVisual());
                }

            }
        }

        public void InvisibleSelectBox()
        {
            if (pointList[0].getPointVisual() != null)
            {
                isVisible = false;

                for (int i = 0; i < pointList.Count(); i++)
                {
                    mainContext.mainViewport.Children.Remove(pointList[i].getPointVisual());
                }
            }
        }
        public void CenterClick(object sender, MouseButtonEventArgs e)
        {
            if (isRotate) return;

            isRotate = true;
            SelectObject = mainContext.viewPortMgr.CurrentSelectObj;
        }



        public void ScaleBoxClick1(object sender, MouseButtonEventArgs e)
        {
            if (pointList[1].isScale) return;

            selectObjectScalePoint(e.GetPosition(mainContext.mainViewport).X, e.GetPosition(mainContext.mainViewport).Y, 1);
            pointList[1].isScale = true;
            SelectObject = mainContext.viewPortMgr.CurrentSelectObj;
        }
        public void ScaleBoxClick2(object sender, MouseButtonEventArgs e)
        {
            if (pointList[2].isScale) return;

            selectObjectScalePoint(e.GetPosition(mainContext.mainViewport).X, e.GetPosition(mainContext.mainViewport).Y, 2);
            pointList[2].isScale = true;
            SelectObject = mainContext.viewPortMgr.CurrentSelectObj;
        }

        public void ScaleBoxClick3(object sender, MouseButtonEventArgs e)
        {
            if (pointList[3].isScale) return;

            selectObjectScalePoint(e.GetPosition(mainContext.mainViewport).X, e.GetPosition(mainContext.mainViewport).Y, 3);
            pointList[3].isScale = true;
            SelectObject = mainContext.viewPortMgr.CurrentSelectObj;
        }

        public void ScaleBoxClick4(object sender, MouseButtonEventArgs e)
        {
            if (pointList[4].isScale) return;

            selectObjectScalePoint(e.GetPosition(mainContext.mainViewport).X, e.GetPosition(mainContext.mainViewport).Y, 4);
            pointList[4].isScale = true;
            SelectObject = mainContext.viewPortMgr.CurrentSelectObj;
        }

        public void ScaleBoxClick5(object sender, MouseButtonEventArgs e)
        {
            if (pointList[5].isScale) return;

            selectObjectScalePoint(e.GetPosition(mainContext.mainViewport).X, e.GetPosition(mainContext.mainViewport).Y, 5);
            pointList[5].isScale = true;
            SelectObject = mainContext.viewPortMgr.CurrentSelectObj;
        }
        public void ScaleBoxClick6(object sender, MouseButtonEventArgs e)
        {
            if (pointList[6].isScale) return;

            selectObjectScalePoint(e.GetPosition(mainContext.mainViewport).X, e.GetPosition(mainContext.mainViewport).Y, 6);
            pointList[6].isScale = true;
            SelectObject = mainContext.viewPortMgr.CurrentSelectObj;
        }
        public void ScaleBoxClick7(object sender, MouseButtonEventArgs e)
        {
            if (pointList[7].isScale) return;

            selectObjectScalePoint(e.GetPosition(mainContext.mainViewport).X, e.GetPosition(mainContext.mainViewport).Y, 7);
            pointList[7].isScale = true;
            SelectObject = mainContext.viewPortMgr.CurrentSelectObj;
        }
        public void ScaleBoxClick8(object sender, MouseButtonEventArgs e)
        {
            if (pointList[8].isScale) return;

            selectObjectScalePoint(e.GetPosition(mainContext.mainViewport).X, e.GetPosition(mainContext.mainViewport).Y , 8);
            pointList[8].isScale = true;
            SelectObject = mainContext.viewPortMgr.CurrentSelectObj;
        }


        public Point mouseStartPoint;
        public int selectNum;



        public void selectObjectScalePoint(double x, double y, int num)
        {
            selectNum = num;
            double changeX = (x * 2 / mainContext.mainViewport.RenderSize.Width - 1) * (0.4 * mainContext.cameraManager.getPoint3D().Z) + mainContext.cameraManager.getPoint3D().X + mainContext.cameraManager.getTranslateTransform().OffsetX;
            double changeY = (y * -2 / mainContext.mainViewport.RenderSize.Height + 1) * (0.16 * mainContext.cameraManager.getPoint3D().Z) + mainContext.cameraManager.getPoint3D().Y + mainContext.cameraManager.getTranslateTransform().OffsetY;

            mouseStartPoint.X = changeX;
            mouseStartPoint.Y = changeY;



        }




        public void setXYZ(TOOL mainContext, Size size, double x, double y, double z, Point3DCollection point3DCollection)
        {
            double changeX = (x * 2 / size.Width - 1) * (0.4 * mainContext.cameraManager.getPoint3D().Z) + mainContext.cameraManager.getPoint3D().X + mainContext.cameraManager.getTranslateTransform().OffsetX;
            double changeY = (y * -2 / size.Height + 1) * (0.16 * mainContext.cameraManager.getPoint3D().Z) + mainContext.cameraManager.getPoint3D().Y + mainContext.cameraManager.getTranslateTransform().OffsetY;

            point.X = x;
            point.Y = y;

            TranslateTransform3D p0 = (pointList[0].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D);

            TranslateTransform3D p1 = (pointList[1].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D);
            TranslateTransform3D p2 = (pointList[2].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D);
            TranslateTransform3D p3 = (pointList[3].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D);
            TranslateTransform3D p4 = (pointList[4].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D);

            TranslateTransform3D p5 = (pointList[5].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D);
            TranslateTransform3D p6 = (pointList[6].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D);
            TranslateTransform3D p7 = (pointList[7].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D);
            TranslateTransform3D p8 = (pointList[8].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D);


            p1.OffsetX = point.X + point3DCollection[0].X;
            p1.OffsetY = point.Y + point3DCollection[0].Y;
            p1.OffsetZ = z;

            p2.OffsetX = point.X + point3DCollection[1].X;
            p2.OffsetY = point.Y + point3DCollection[1].Y;
            p2.OffsetZ = z;

            p3.OffsetX = point.X + point3DCollection[2].X;
            p3.OffsetY = point.Y + point3DCollection[2].Y;
            p3.OffsetZ = z;

            p4.OffsetX = point.X + point3DCollection[3].X;
            p4.OffsetY = point.Y + point3DCollection[3].Y;
            p4.OffsetZ = z;

            for (int i = 0; i < pointList.Count(); i++)
            {
                (pointList[i].getPoint3DCollection().Children.ElementAt(2) as RotateTransform3D).CenterX = point.X;
                (pointList[i].getPoint3DCollection().Children.ElementAt(2) as RotateTransform3D).CenterY = point.Y;
                (pointList[i].getPoint3DCollection().Children.ElementAt(2) as RotateTransform3D).CenterZ = point.Z;

            }
            squreCenterPoint();

            p5.OffsetX = (p4.OffsetX + p1.OffsetX) / 2;
            p5.OffsetY = (p4.OffsetY + p1.OffsetY) / 2;

            p6.OffsetX = (p1.OffsetX + p2.OffsetX) / 2;
            p6.OffsetY = (p1.OffsetY + p2.OffsetY) / 2;

            p7.OffsetX = (p2.OffsetX + p3.OffsetX) / 2;
            p7.OffsetY = (p2.OffsetY + p3.OffsetY) / 2;

            p8.OffsetX = (p3.OffsetX + p4.OffsetX) / 2;
            p8.OffsetY = (p3.OffsetY + p4.OffsetY) / 2;

        }


        public void squreCenterPoint()
        {
            TranslateTransform3D p1 = (pointList[1].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D);
            TranslateTransform3D p2 = (pointList[2].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D);
            TranslateTransform3D p3 = (pointList[3].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D);
            TranslateTransform3D p4 = (pointList[4].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D);

            Point triangle1Center = new Point();
            triangle1Center.X = (p1.OffsetX + p3.OffsetX + p2.OffsetX) / 3;
            triangle1Center.Y = (p1.OffsetY + p3.OffsetY + p2.OffsetY) / 3;

            Point triangle2Center = new Point();
            triangle2Center.X = (p1.OffsetX + p4.OffsetX + p3.OffsetX) / 3;
            triangle2Center.Y = (p1.OffsetY + p4.OffsetY + p3.OffsetY) / 3;


            Point triangle3Center = new Point();
            triangle3Center.X = (p1.OffsetX + p2.OffsetX + p4.OffsetX) / 3;
            triangle3Center.Y = (p1.OffsetY + p2.OffsetY + p4.OffsetY) / 3;

            Point triangle4Center = new Point();
            triangle4Center.X = (p2.OffsetX + p3.OffsetX + p4.OffsetX) / 3;
            triangle4Center.Y = (p2.OffsetY + p3.OffsetY + p4.OffsetY) / 3;

            CenterPoint.X = (triangle1Center.X + triangle2Center.X) / 2;
            CenterPoint.Y = (triangle1Center.Y + triangle2Center.Y) / 2;


            (pointList[0].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D).OffsetX = CenterPoint.X;
            (pointList[0].getPoint3DCollection().Children.ElementAt(0) as TranslateTransform3D).OffsetY = CenterPoint.Y;

            CenterPoint.X = point.X;
            CenterPoint.Y = point.Y;


        }

        public void setRotate(double degree)
        {

            AxisAngleRotation3D r = new AxisAngleRotation3D();
            r.Angle = degree;
            r.Axis = new Vector3D(0, 0, 1);
            for (int i = 0; i < pointList.Count(); i++)
            {
                (pointList[i].getPoint3DCollection().Children.ElementAt(2) as RotateTransform3D).Rotation = r;

            }
        }

        public Point3D getPosition()
        {
            return point;
        }
    }
}
